import { StatusCodes } from 'http-status-codes';
import logger from '../config/logger.js';

/**
 * 自定义错误类 - 应用错误
 */
export class AppError extends Error {
  constructor(message, statusCode) {
    super(message);
    this.statusCode = statusCode;
    this.status = `${statusCode}`.startsWith('4') ? 'fail' : 'error';
    this.isOperational = true;
    Error.captureStackTrace(this, this.constructor);
  }
}

/**
 * 404 Not Found 错误处理
 */
export const notFound = (req, res, next) => {
  const error = new AppError(`无法找到 ${req.originalUrl}`, StatusCodes.NOT_FOUND);
  next(error);
};

/**
 * 全局错误处理中间件
 */
export const errorHandler = (err, req, res, next) => {
  // 设置默认状态码和错误信息
  err.statusCode = err.statusCode || StatusCodes.INTERNAL_SERVER_ERROR;
  err.status = err.status || 'error';

  // 记录错误
  if (err.statusCode >= 500) {
    logger.error(`[${new Date().toISOString()}] ${err.stack}`);
  } else {
    logger.warn(`[${new Date().toISOString()}] ${err.message}`);
  }

  // 开发环境：发送详细的错误信息
  if (process.env.NODE_ENV === 'development') {
    res.status(err.statusCode).json({
      success: false,
      status: err.status,
      message: err.message,
      stack: err.stack,
      error: err,
    });
  } 
  // 生产环境：发送简化的错误信息
  else {
    // 操作错误，可以发送给客户端
    if (err.isOperational) {
      res.status(err.statusCode).json({
        success: false,
        message: err.message,
      });
    } 
    // 编程错误或其他未知错误，不发送详细信息给客户端
    else {
      // 1) 记录错误
      logger.error('ERROR 💥', err);
      
      // 2) 发送通用错误响应
      res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
        success: false,
        message: '服务器内部错误',
      });
    }
  }
};

/**
 * 处理JWT错误
 */
export const handleJWTError = () =>
  new AppError('无效的令牌，请重新登录', StatusCodes.UNAUTHORIZED);

/**
 * 处理JWT过期错误
 */
export const handleJWTExpiredError = () =>
  new AppError('登录已过期，请重新登录', StatusCodes.UNAUTHORIZED);

/**
 * 处理数据库重复字段错误
 */
export const handleDuplicateFieldsDB = (err) => {
  const value = err.message.match(/(["'])(\\?.)*?\1/)[0];
  const message = `字段值 ${value} 已存在，请使用其他值`;
  return new AppError(message, StatusCodes.BAD_REQUEST);
};

/**
 * 处理验证错误
 */
export const handleValidationErrorDB = (err) => {
  const errors = Object.values(err.errors).map((el) => el.message);
  const message = `无效的输入数据: ${errors.join('. ')}`;
  return new AppError(message, StatusCodes.BAD_REQUEST);
};
